package com.caldremch.androidfoundation.http.request;


import com.caldremch.androidfoundation.http.ApiManager;
import com.caldremch.androidfoundation.http.ApiObserver;
import com.caldremch.androidfoundation.http.callback.AbsCallback;
import com.caldremch.androidfoundation.http.func.ApiFunc;
import com.caldremch.androidfoundation.http.model.MediaTypes;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;

/**
 * @Description: Post请求
 * @author: <a href="http://www.xiaoyaoyou1212.com">DAWI</a>
 * @date: 2017-04-28 16:06
 */
public class PostRequest extends BaseHttpRequest<PostRequest> {

//    protected Map<String, Object> forms = new LinkedHashMap<>();
    protected RequestBody mRequestBody;
    protected MediaType mMediaType;
    protected String mContent;

    public PostRequest(String suffixUrl) {
        super(suffixUrl);
    }

    @Override
    protected <T> Observable<T> execute(Type type) {

        if (mContent != null && mMediaType != null) {
            mRequestBody = RequestBody.create(mMediaType, mContent);
            return mApiService.postBody(mSuffixUrl, mRequestBody).compose(this.<T>norTransformer(type));
        }
        return mApiService.post(mSuffixUrl, mParams).compose(this.<T>norTransformer(type));

    }

    protected <T> ObservableTransformer<ResponseBody, T> norTransformer(final Type type) {
        return new ObservableTransformer<ResponseBody, T>() {
            @Override
            public ObservableSource<T> apply(Observable<ResponseBody> apiResultObservable) {
                return apiResultObservable
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .map(new ApiFunc<T>(type))
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }



    @Override
    protected <T> void execute(AbsCallback<T> callback) {

        DisposableObserver disposableObserver = new ApiObserver(callback);

        if (super.mTag != null) {

            ApiManager.get().add(super.mTag, disposableObserver);

        }
//        this.execute(getType(callback)).subscribe(disposableObserver);

//        if (mRequestBody != null) {
//            return mApiService.postBody(mSuffixUrl, mRequestBody).compose(disposableObserver);
//        }

        this.execute(getType(callback)).subscribe(disposableObserver);

    }


    /**
     * 获取第一级type
     *
     * @param t
     * @param <T>
     * @return
     */
    protected <T> Type getType(T t) {
        Type genType = t.getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        Type type = params[0];
        Type finalNeedType;
        if (params.length > 1) {
            if (!(type instanceof ParameterizedType)) throw new IllegalStateException("没有填写泛型参数");
            finalNeedType = ((ParameterizedType) type).getActualTypeArguments()[0];
        } else {
            finalNeedType = type;
        }
        return finalNeedType;
    }

    /**
     * 获取次一级type(如果有)
     *
     * @param t
     * @param <T>
     * @return
     */
    protected <T> Type getSubType(T t) {
        Type genType = t.getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        Type type = params[0];
        Type finalNeedType;
        if (params.length > 1) {
            if (!(type instanceof ParameterizedType)) throw new IllegalStateException("没有填写泛型参数");
            finalNeedType = ((ParameterizedType) type).getActualTypeArguments()[0];
        } else {
            if (type instanceof ParameterizedType) {
                finalNeedType = ((ParameterizedType) type).getActualTypeArguments()[0];
            } else {
                finalNeedType = type;
            }
        }
        return finalNeedType;
    }


    public PostRequest setRequestBody(RequestBody requestBody) {
        this.mRequestBody = requestBody;
        return this;
    }

    public PostRequest setString(String string) {
        this.mContent = string;
        this.mMediaType = MediaTypes.TEXT_PLAIN_TYPE;
        return this;
    }

    public PostRequest setString(String string, MediaType mediaType) {
        this.mContent = string;
        this.mMediaType = mediaType;
        return this;
    }

    public PostRequest setJson(String json) {
        this.mContent = json;
        this.mMediaType = MediaTypes.APPLICATION_JSON_TYPE;
        return this;
    }

    public PostRequest setJson(JSONObject jsonObject) {
        this.mContent = jsonObject.toString();
        this.mMediaType = MediaTypes.APPLICATION_JSON_TYPE;
        return this;
    }

    public PostRequest setJson(JSONArray jsonArray) {
        this.mContent = jsonArray.toString();
        this.mMediaType = MediaTypes.APPLICATION_JSON_TYPE;
        return this;
    }
}
